/*
* Copyright (c) 2018-2022 Allwinner Technology Co. Ltd. All rights reserved.
* Author: BT Team
* Date: 2022.03.12
*/

#ifndef __BT_HAL_H__
#define __BT_HAL_H__

#include "bt_dev_list.h"
#include "bt_log.h"
#include "bt_manager.h"
#include "ms_hal_ble.h"
#include "strings.h"
#include <byteswap.h>
#include <stdio.h>

#define LE_ADV_HANDLE 60000
#define NONNECT_LE_ADV_HANDLE 60001
#define SERVER_HANDLE_ID 60002
#define BLE_NUM_LIMIT 512

typedef enum {
    LD_HAL_BLE_STATUS_OFF = 0x00, //!< ble stack init success
    LD_HAL_BLE_STATUS_ON,         //!< ble stack stop success
} ld_hal_ble_stack_status_t;

typedef struct {
    int conn_id;
    uint8_t addr[6];
    uint8_t is_slave;
    int addr_type;
} ble_gatt_data_t;

extern ble_gatt_data_t ble_list[BLE_NUM_LIMIT]; // device num limit

void bt_gatt_client_register_callback(btmg_callback_t *cb);
void bt_gatt_server_register_callback(btmg_callback_t *cb);
void bt_register_callback(void);
int bt_init(void);
int bt_deinit(void);
ms_hal_result_t ble_legacy_adv_stop(uint16_t handle);
ms_hal_result_t nonconn_ble_legacy_adv_stop(uint16_t handle);
uint16_t ble_legacy_adv_start(ms_hal_ble_gap_adv_params *param, ms_hal_ble_gap_adv_data *adv_data, uint8_t enable);
uint16_t nonconn_ble_legacy_adv_start(ms_hal_ble_gap_adv_params *param, ms_hal_ble_gap_adv_data *adv_data, uint8_t enable);
uint8_t ble_adv_status(uint16_t handle);
uint8_t nonconn_ble_adv_status(uint16_t handle);
uint8_t get_device_from_id(uint16_t conn_hdl);
ble_gatt_data_t *get_addr_from_id(uint16_t conn_hdl);
uint8_t add_device_to_list(ble_gatt_data_t device);
void del_device_to_list(int conn_id);
ms_hal_result_t ble_scan_start(ms_hal_ble_scan_params_t *params, ms_hal_ble_scan_callback_t function);
uint8_t get_ble_scan_status(void);
ms_hal_result_t ble_scan_stop(void);
ms_hal_result_t ble_scan_start(ms_hal_ble_scan_params_t *params, ms_hal_ble_scan_callback_t function);
ms_hal_result_t ble_gatt_service_add(ms_hal_ble_service_t *service);
int ble_discovery_all_service(int flag, uint16_t conn_hdl);
ms_hal_result_t ble_gatt_data_send(uint16_t conn_hdl, ms_hal_ble_gatts_attr_handle_t *handle, uint8_t *data, uint16_t len);
ms_hal_result_t ble_gatt_write(uint8_t type, uint16_t conn_hdl, uint16_t att_handle, uint16_t len, uint8_t *data);
ms_hal_result_t ble_conn_start(ms_hal_ble_conn_param_t *param, ms_hal_ble_addr_t *target);
ms_hal_result_t set_ble_name(char *device_name, int len);
/*a2dp src*/
ms_hal_result_t ms_hal_ble_stack_stop_service_clean(void);
#include <errno.h>
#include <stddef.h>
#include <stdio.h>

#undef MIN
#undef MAX
#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
#define MAX(X, Y) ((X) > (Y) ? (X) : (Y))

#if 1
static int char2hex(char c, uint8_t *x) {
    if (c >= '0' && c <= '9') {
        *x = c - '0';
    } else if (c >= 'a' && c <= 'f') {
        *x = c - 'a' + 10;
    } else if (c >= 'A' && c <= 'F') {
        *x = c - 'A' + 10;
    } else {
        return -EINVAL;
    }

    return 0;
}

static int hex2char(uint8_t x, char *c) {
    if (x <= 9) {
        *c = x + '0';
    } else if (x >= 10 && x <= 15) {
        *c = x - 10 + 'a';
    } else {
        return -EINVAL;
    }

    return 0;
}

static size_t hex2bin(const char *hex, size_t hexlen, uint8_t *buf, size_t buflen) {
    uint8_t dec;

    if (buflen < hexlen / 2 + hexlen % 2) {
        return 0;
    }

    /* if hexlen is uneven, insert leading zero nibble */
    if (hexlen % 2) {
        if (char2hex(hex[0], &dec) < 0) {
            return 0;
        }
        buf[0] = dec;
        hex++;
        buf++;
    }

    /* regular hex conversion */
    for (size_t i = 0; i < hexlen / 2; i++) {
        if (char2hex(hex[2 * i], &dec) < 0) {
            return 0;
        }
        buf[i] = dec << 4;

        if (char2hex(hex[2 * i + 1], &dec) < 0) {
            return 0;
        }
        buf[i] += dec;
    }

    return hexlen / 2 + hexlen % 2;
}

static size_t bin2hex(const uint8_t *buf, size_t buflen, char *hex, size_t hexlen) {
    if ((hexlen + 1) < buflen * 2) {
        return 0;
    }

    for (size_t i = 0; i < buflen; i++) {
        if (hex2char(buf[i] >> 4, &hex[2 * i]) < 0) {
            return 0;
        }
        if (hex2char(buf[i] & 0xf, &hex[2 * i + 1]) < 0) {
            return 0;
        }
    }

    hex[2 * buflen] = '\0';
    return 2 * buflen;
}
#endif

#endif